<?php

namespace platform\models;

use common\base\BaseBackendActiveRecord;
use common\enum\Enum;
use common\models\Circuit;
use common\models\CircuitAddress;
use common\models\OpenCity;
use common\models\Order;
use common\models\Shift;
use common\models\Site;
use common\services\Authorization;
use cm;
use common\models\CircuitTag;
use Yii;
use yii\behaviors\TimestampBehavior;
use yii\db\Expression;
use yii\helpers\ArrayHelper;
use yii\helpers\Url;
use Exception;
use platform\core\BaseModel;

/**
 * This is the model class for table "circuit".
 *
 * @property int $id 自增
 * @property string $name 线路名称
 * @property string|null $serial_number 编号
 * @property int $city_scode 出发区域
 * @property int $site_sid 出发站点ID
 * @property string $s_address 上车地址
 * @property int $site_eid 终点站点ID
 * @property int $city_ecode 终点区域
 * @property string $e_address 下车地址
 * @property string $duration 时长
 * @property int $mileage 公里数
 * @property int $is_hot 是否热门：0：正常；1：热门
 * @property int $status 状态：1：正常；0：停用；2：删除；
 * @property string $addtime 创建时间
 * @property string $updatetime 更新时间
 * @property int  $rebate_status 分销开关 0关1开
 * @property int  $rebate_type 分销方式 1售价比例 2金额
 * @property float|null  $rebate 分销金额/比例
 */
class CircuitModel extends BaseBackendActiveRecord
{

    /**
     * {@inheritdoc}
     */
    public static function tableName()
    {
        return 'circuit';
    }

    /**
     * {@inheritdoc}
     */
    public function rules()
    {
        return [
            [['name', 'serial_number', 's_address', 'e_address',], 'required'],
            [['name','serial_number','s_address','e_address','duration'], 'string'],
            [['addtime','updatetime'], 'safe'],
            [['city_scode', 'site_sid','site_eid','city_ecode','mileage','is_hot','status','rebate_status','rebate_type'], 'integer'],
            [['rebate'],'number']
        ];
    }
    /**
     * {@inheritdoc}
     */
    public function attributeLabels()
    {
        return [
            'id' => '自增',
            'name' => '线路名称',
            'serial_number' => '编号',
            'city_scode' => '出发区域',
            'site_sid' => '出发站点ID',
            's_address' => '上车地址',
            'site_eid' => '终点站点ID',
            'city_ecode' => '终点区域',
            'e_address' => '下车地址',
            'duration' => '时长',
            'mileage' => '公里数',
            'is_hot' => '是否热门',
            'status' => '状态',
            'addtime' => '添加时间',
            'updatetime' => '更新时间',
            'rebate_status'=>'分销开关',
            'rebate_type'=>'分销方式',
            'rebate'=>'分销金额'
        ];
    }

    /**
     * @inheritdoc
     */
    public function behaviors()
    {
        return [
            [
                'class' => TimestampBehavior::className(),
                'createdAtAttribute' => 'addtime',// 自己根据数据库字段修改
                'updatedAtAttribute' => 'updatetime', // 自己根据数据库字段修改, // 自己根据数据库字段修改
                //'value'   => new Expression('NOW()'),
                'value'   => function(){return date('Y-m-d H:i:s',time());},
            ],
        ];
    }

    /*
    * 线路管理
    */
    public function actionIndex()
    {

        if (Cm::$req->isPost()) {
            $action = Cm::$req->get('action');
            switch ($action) {
                case "list":
                    $this->list();
                    break;
                case 'save':
                    $this->saves();
                    break;
                case 'del':
                    $id = Cm::$req->post('id', ['null', 'empty', 'default' => 0]);
                    if(empty($id)){
                        Cm::$res->error('请选择删除开通的线路');
                    }
                    $mdata = ['status' => 2,'updatetime' => date("Y-m-d H:i:s",time())];
                    Cm::$db->update("circuit", $mdata, "id={$id}");
                    Cm::$app->log->authlog(35,$mdata,$id);
                    Cm::$res->susess();
                    break;
                case 'tag_info':
                    $id = Cm::$req->post('id', ['null', 'empty', 'default' => 0]);
                    if(empty($id)){
                        Cm::$res->error('参数错误,请选择获取标签的线路');
                    }
                    $tags = Cm::$db->all("SELECT * FROM circuit_tag WHERE circuit_id={$id} AND status=1 ORDER BY sort");
                    Cm::$app->log->authlog(36,$tags,$id);
                    Cm::$res->susess($tags);
                    break;
                case 'tag_save':
                    $id = Cm::$req->post('id', ['null', 'empty', 'default' => 0]);
                    $mdata = [
                        'name' => trim(Cm::$req->post('name',['title'=>'标签名称'])),
                        'sort' => Cm::$req->post('sort',['null','empty','default'=>0]),
                        'circuit_id' => Cm::$req->post('circuit_id',['null','empty','default'=>0]),
                        'updatetime' => date("Y-m-d H:i:s",time())
                    ];
                    if(empty($mdata['circuit_id'])){
                        Cm::$res->error('参数错误,请选择保存标签的线路');
                    }
                    $hastag = Cm::$db->one("SELECT id FROM circuit_tag WHERE status=1 AND name='{$mdata['name']}' AND circuit_id={$mdata['circuit_id']} AND id!={$id}");
                    if(!empty($hastag)){
                        Cm::$res->error('该线路下已存在该标签');
                    }
                    if(!empty($id)){
                        Cm::$db->update('circuit_tag', $mdata, "id={$id}");
                        Cm::$app->log->authlog(37,$mdata,$id);
                    }else{
                        $mdata['addtime'] = date('Y-m-d H:i:s');
                        $mdata['status'] = 1;
                        $id = Cm::$db->insert('circuit_tag', $mdata);
                        if(!$id){
                            Cm::$res->error('保存失败');
                        }
                        Cm::$app->log->authlog(38,$mdata,$id);
                    }
                    $tags = Cm::$db->all("SELECT * FROM circuit_tag WHERE circuit_id={$mdata['circuit_id']} AND status=1 ORDER BY sort");
                    Cm::$res->susess($tags, '保存成功');
                    break;
                case 'tag_del':
                    $id = Cm::$req->post('id', ['null', 'empty', 'default' => 0]);
                    if(empty($id)){
                        Cm::$res->error('请选择删除的标签');
                    }
                    $mdata = ['status' => 2,'updatetime' => date("Y-m-d H:i:s",time())];
                    Cm::$db->update("circuit_tag", $mdata, "id={$id}");
                    Cm::$app->log->authlog(39,$mdata,$id);
                    Cm::$res->susess();
                    break;
                case 'state':
                    $id = Cm::$req->post('id', ['null', 'empty', 'default' => 0]);
                    $status = Cm::$req->post('status', ['null', 'empty', 'default' => 1]);
                    if($status!=1 && $status!=0){
                        Cm::$res->error('操作错误！');
                    }
                    $str = $status == 1 ? '停用':'启用';
                    if(empty($id)){
                        Cm::$res->error('请选择要'.$str.'的线路');
                    }
                    $status = $status == 1 ? 0 : 1;
                    $mdata = ['status' => $status,'updatetime' => date("Y-m-d H:i:s",time())];
                    Cm::$db->update("circuit", $mdata, "id={$id}");
                    Cm::$app->log->authlog(40,$mdata,$id);
                    Cm::$res->susess();
                    break;
                case 'order':
                    $id = Cm::$req->post('id', ['null', 'empty', 'default' => 0]);
                    if(empty($id)){
                        Cm::$res->error("请选择订单统计的线路");
                    }
                    $order = Cm::$db->all("SELECT COUNT(id) AS num,'isok' AS type FROM `order` WHERE circuit_id={$id} AND status=1 AND order_status<>5
                                        UNION ALL
                                        SELECT COUNT(id) AS num,'isno' AS type FROM `order` WHERE circuit_id={$id} AND order_status=5
                                        UNION ALL
                                        SELECT COUNT(id) AS num,'pay' AS type FROM `order` WHERE circuit_id={$id} AND pay_status=1 AND refund_status=0
                                        UNION ALL
                                        SELECT COUNT(id) AS num,'refund' AS type FROM `order` WHERE circuit_id={$id} AND status=2
                                        UNION ALL
                                        SELECT COUNT(id) AS num,'change' AS type FROM `order` WHERE circuit_id={$id} AND status=3
                                        UNION ALL
                                        SELECT COUNT(id) AS num,'cancel' AS type FROM `order` WHERE circuit_id={$id} AND status=0
                                        UNION ALL
                                        SELECT COUNT(id) AS num,'overtime' AS type FROM `order` WHERE circuit_id={$id} AND status=1 AND order_status=5");
                    $info = [];
                    $types = [
                        'isok' => '有效订单',
                        'isno' => '无效订单',
                        'pay' => '支付订单',
                        'refund' => '退款订单',
                        'change' => '改签订单',
                        'cancel' => '取消订单',
                        'overtime' => '超时订单'
                    ];
                    $info['data'] = [
                        'name' => "订单量",
                        'type' => "bar",
                        't' => "n",
                        'data' => [],
                        'label'=> [
                            'show'=> true,
                            'position'=> 'top'
                        ]
                    ];
                    foreach ($order as $s) {
                        $name = $types[$s['type']];
                        $info['name'][] = $name;
                        $info['data']['data'][] = $s['num'];
                    }
                    Cm::$res->susess($info);
                    break;
            }
        }

        $data['map'] = [];
        $data['map'][] = ['title' => "站点管理", 'url' => Url::to(['site/index'])];
        $data['map'][] = ['title' => "线路管理", 'url' => Url::to(['circuit/index'])];
        $data['baseUrl'] = Url::to(['circuit/index']);
        $data['shiftUrl'] = Url::to(['shift/index']);
        $data['allSite'] = (new BaseModel())->allSite();
        $data['SiteData']=Site::find()->andWhere(['status'=>Enum::STATUS_NORMAL])->select(['id','name'])->asArray()->all();
        $data['carModels'] = (new BaseModel())->carModels();
        $data['allInspector'] = (new BaseModel())->getInspector();
        $data['allssite'] = (new BaseModel())->getAllShiftSsite();
        $data['allesite'] = (new BaseModel())->getAllShiftEsite();
        $data['allscity'] = (new BaseModel())->getAllShiftScity();
        $data['allecity'] = (new BaseModel())->getAllShiftEcity();
        return $data;
    }

    /**
     * 列表
     */
    public function list(){
        $params=Yii::$app->request->post();

        $query=self::find();
        $where=[];
        if(!empty($params['ssite']))$where['site_sid']=$params['ssite'];
        if(!empty($params['esite']))$where['site_eid']=$params['esite'];
        if(!empty($params['scity']))$where['city_scode']=$params['scity'];
        if(!empty($params['ecity']))$where['city_ecode']=$params['ecity'];
        if(!empty($params['is_hot'])){
            $where['is_hot']=$params['is_hot'];
            if($params['is_hot']==2)$where['is_hot']=0;
        }
        if(!empty($params['is_status'])){
            $where['status']=$params['is_status'];
            if($params['is_status']==2)$where['status']=0;
        }else{
            $query->andWhere(['!=','status',2]);
        }
        if(!empty($params['id'])){
            $query->andWhere(['id'=>$params['id']]);
        }
        if(!empty($params['key'])){
            $query->andWhere(['like','name',$params['key']]);
        }
        $page = $params['page'];
        $size = $params['limit'];
        $query->andWhere($where)->orderBy(['id'=>SORT_DESC])->limit($size)->offset(($page - 1) * $size);

        $data['count']=$query->count();
        $data['data'] =$query->asArray()->all();
        $ids=array_column($data['data'],'id');
        $city_scode=array_column($data['data'],'city_scode');
        $city_ecode=array_column($data['data'],'city_ecode');
        $site_sid=array_column($data['data'],'site_sid');
        $site_eid=array_column($data['data'],'site_eid');
        $sarea_data=OpenCity::find()->andWhere(['code'=>array_unique($city_scode)])
            ->andWhere(['status'=>Enum::STATUS_NORMAL])
            ->select([new Expression("CONCAT_WS('|',CONCAT_WS(',',province,city,full_name),parentpath) AS areas")])
            ->indexBy('code')
            ->column();
        $earea_data=OpenCity::find()->andWhere(['code'=>array_unique($city_ecode)])
            ->andWhere(['status'=>Enum::STATUS_NORMAL])
            ->select([new Expression("CONCAT_WS('|',CONCAT_WS(',',province,city,full_name),parentpath) AS earea")])
            ->indexBy('code')
            ->column();
        $ssite_data=Site::find()->andWhere(['id'=>array_unique($site_sid),'status'=>Enum::STATUS_NORMAL])
            ->select(['full_name'])
            ->indexBy('id')
            ->column();
        $esite_data=Site::find()->andWhere(['id'=>array_unique($site_eid),'status'=>Enum::STATUS_NORMAL])
            ->select(['full_name'])
            ->indexBy('id')
            ->column();
        $tags_data=CircuitTag::find()->andWhere(['circuit_id'=>$ids,'status'=>Enum::STATUS_NORMAL])
            ->select([new Expression("GROUP_CONCAT(name) AS tags")])
            ->orderBy(['sort'=>SORT_DESC])
            ->indexBy('circuit_id')
            ->column();
        $orderstr_data=Order::find()->andWhere(['circuit_id'=>$ids,'status'=>Enum::STATUS_NORMAL])
            ->andWhere(['<>','order_status',Order::STATUS_INVALID])
            ->select([new Expression("CONCAT_WS(',',SUM(ridership),COUNT(id)) AS num")])
            ->indexBy('circuit_id')
            ->column();

        $adress=CircuitAddress::find()->andWhere(['circuit_id'=>$ids,'type'=>CircuitAddress::TYPE_GETON,'is_del'=>CircuitAddress::IS_DEL_NO])
            ->select(['circuit_id','site_id'])
            ->asArray()
            ->all();
        $adress=ArrayHelper::index($adress,null,'circuit_id');
        foreach ($data['data'] as $key => &$value) {
            $value['sarea']=$sarea_data[$value['city_scode']]??'';
            $value['earea']=$earea_data[$value['city_ecode']]??'';
            $value['ssite']=$ssite_data[$value['site_sid']]??'';
            $value['esite']=$esite_data[$value['site_eid']]??'';
            $value['tags']=$tags_data[$value['id']]??'';
            $value['orderstr']=$orderstr_data[$value['id']]??'';
            if(!empty($value['sarea'])){
                $arr = explode('|', $value['sarea']);
                $value['scode']  = explode(',', $arr[1]);
                $sarea = explode(',', $arr[0]);
                if(count($value['scode'] ) == 1){
                    $value['sarea'] = $sarea[2];
                }else if(count($value['scode'] ) == 2){
                    $value['sarea'] = $sarea[0].','.$sarea[2];
                }
            }else{
                $value['sarea'] = '';
                $value['scode'] = [];
            }
            if(!empty($value['earea'])){
                $arr = explode('|', $value['earea']);
                $value['ecode']  = explode(',', $arr[1]);
                $earea = explode(',', $arr[0]);
                if(count($value['ecode']) == 1){
                    $value['earea'] = $earea[2];
                }else if(count($value['ecode'] ) == 2){
                    $value['earea'] = $earea[0].','.$earea[2];
                }
            }else{
                $value['earea'] = '';
                $value['ecode'] = [];
            }
            $orderstr = explode(",", $value['orderstr']);
            $value['passengernum'] = $orderstr[0].'人';
            $value['ordernum'] = empty($orderstr[1]) ? '0笔' : $orderstr[1].'笔';
            $value['address']=[];
            if(!empty($adress[$value['id']])){
                $value['address']=array_column($adress[$value['id']],'site_id');
                $key=array_search($value['site_sid'],$value['address']);
                if($key!==false){
                    unset($value['address'][$key]);
                }
                $value['address']=array_merge($value['address'],[]);
                $value['point_address']=CircuitAddress::find()->alias('ca')
                    ->leftJoin(['s'=>Site::tableName()],['s.id'=>new Expression('ca.site_id')])
                    ->andWhere(['ca.circuit_id'=>$value['id'],'ca.site_id'=>$value['address']])
                    ->select(['ca.id','s.name','ca.address'])
                    ->asArray()->all();
            }else{
                $value['address']=[];
                $value['point_address']=[];
            }
        }
        if($params['limit']==1){
            $data['data']=current($data['data']);
        }
        Cm::$res->paging($data);
    }
    /**
     * 编辑、添加
     */
    public  function saves(){
        $transaction=Yii::$app->getDb()->beginTransaction();
        try {
            if(Cm::$redis->Exists('is_err'))throw new Exception(Cm::$redis->get('is_err'));
            $params=Yii::$app->request->post();
            if(empty($params['s_address']))throw new Exception('上车地址未填写');
            $point_address=$params['point_address']??[];
            $point_address_s=$params['point_address_s']??[];
            $point_data=[];
            foreach ($point_address as $k=>$site_id){
                $point_data[$site_id]=[
                    'site_id'=>$site_id,
                    'address'=>$point_address_s[$k]
                ];
            }
            $point_data[$params['site_sid']]=[
                'site_id'=>$params['site_sid'],
                'address'=>$params['s_address']
            ];
            $point_data[$params['site_eid']]=[
                'site_id'=>$params['site_eid'],
                'address'=>$params['e_address']
            ];
            $all_address=array_merge([$params['site_sid'],$params['site_eid']],$point_address);
            if(count($all_address)!=count(array_unique($all_address)))throw new Exception('请检查上车地址是否存在相同地址');
            if($params['e_address']==$params['s_address'])throw new Exception('请检查上车地址与下车是否存在相同地址');
            $id=$params['id']??0;

            if(!empty($params['rebate_status'])){
                if(empty($params['rebate_type']))throw new Exception('请选择分销方式');
                if(empty($params['rebate']))throw new Exception('请设置分销金额/比列');
            }
            if($params['rebate_type']==SysModel::REBATE_TYPE_RATIO&&($params['rebate']>100||$params['rebate']<0))throw new Exception('分销比列设置错误,比例不应大于100,也不应小于0.01');
            if($params['rebate_type']==SysModel::REBATE_TYPE_PRICE&&$params['rebate']<0)throw new Exception('分销金额设置错误,不应小于0.01');
            if(empty($id)){
                $model=new self();
                $model->setAttributes($params);
                if(!$model->save())throw new Exception('保存失败,'.current($model->getFirstErrors()));
                $id=$model->id;
                Cm::$app->log->authlog(33,$params,$id);

                $add_address=$all_address;
            }else{
                foreach (Shift::find()->andWhere(['status'=>Enum::STATUS_NORMAL])->each() as $shift){
                    /**@var $shift Shift*/
                    if($params['rebate_type']==SysModel::REBATE_TYPE_RATIO){
                        $rebate=sprintf("%.2f",$shift->ticket_price*$params['rebate']/100);
                    }else{
                        $rebate=$params['rebate'];
                    }
                    if($rebate>=$shift->ticket_price){
                        throw new Exception('分销金额大于等于 该班次'.$shift->departuretime.'票价金额');
                    }
                }
                $model=self::findOne($id);
                $model->setAttributes($params);
                if(!$model->save())throw new Exception('保存失败'.current($model->getFirstErrors()));
                Cm::$app->log->authlog(34,$params,$id);

                $query=CircuitAddress::find()->andWhere(['circuit_id'=>$id,'site_id'=>$all_address,'is_del'=>Enum::STATUS_NORMAL]);
                $old_address=(clone $query)->select(['site_id'])->column();
                foreach ((clone $query)->each() as $each){
                    /** @var $each CircuitAddress */
                    if($each->address!=$point_data[$each->site_id]['address']){
                        $each->address=$point_data[$each->site_id]['address'];
                        if(!$each->save())throw new Exception(current($each->getFirstErrors()));
                    }
                }
                $public_address=array_intersect($old_address,$all_address);
                CircuitAddress::updateAll(['is_del'=>CircuitAddress::IS_DEL_YES],['and',['not in','site_id',$public_address],['circuit_id'=>$id],['type'=>CircuitAddress::TYPE_GETON]]);
                $add_address=array_diff($all_address,$public_address);
            }
            $key = array_search($params['site_eid'], $add_address);
            if ($key !== false) {
                unset($add_address[$key]);
            }
            $data=[];
            $time=time();
            foreach ($add_address as $address){
                $data[]=[
                    'site_id'=>$address,
                    'address'=>$point_data[$address]['address'],
                    'circuit_id'=>$id,
                    'type'=>CircuitAddress::TYPE_GETON,
                    'created_at'=>$time,
                    'updated_at'=>$time,
                ];
            }
            $e_address_id=$params['site_eid'];
            if(!CircuitAddress::find()
                ->andWhere(['site_id'=>$e_address_id,'circuit_id'=>$id,'is_del'=>CircuitAddress::IS_DEL_NO,'type'=>CircuitAddress::TYPE_GETOFF])->exists()){
                $data[]=[
                    'site_id'=>$e_address_id,
                    'address'=>$point_data[$e_address_id]['address'],
                    'circuit_id'=>$id,
                    'type'=>CircuitAddress::TYPE_GETOFF,
                    'created_at'=>$time,
                    'updated_at'=>$time,
                ];
            }
            if(count($data)){
                $num=CircuitAddress::getDb()->createCommand()->batchInsert(CircuitAddress::tableName(),array_keys(current($data)),$data)->execute();
                if($num!=count($data))throw new Exception('保存失败');
            }
            $transaction->commit();
            Cm::$res->susess([], '保存成功');
        }catch(Exception $e){
            $transaction->rollback();
            Cm::$res->error($e->getMessage());
        }
    }
}